package com.sen.common.jquery;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * jquery tinygrid控件前/后台交互的数据转化工具类.
 * 
 * 主要用于转换列表(List)数据变成前后需要JSON格式的数据.
 * 
 * @author sen
 */
public final class TinyGridUtils {
	/**
	 * 默认的时间输出格式: yyyy-MM-dd HH:mm. 精确到分钟.
	 */
	public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm";

	private static final Logger LOG = LoggerFactory.getLogger(TinyGridUtils.class);
	
	private TinyGridUtils() {
		// empty!
	}
	
	/**
	 * 把列表信息转化成json格式, 没有分页信息.
	 * 
	 * @param beans
	 *            要输出到前台的列表信息.
	 * @param properties
	 *            前台需要展现的JavaBean属性.
	 * @return json格式的字符串.
	 */
	public static String toJson(List<?> beans, String[] properties) {
		return toJson(beans, properties, null);
	}

	/**
	 * 把列表信息转化成json格式, 不分页.
	 * 
	 * @param beans
	 *            要输出到前台的列表信息.
	 * @param properties
	 *            前台需要展现的JavaBean属性.
	 * @param dateFormat
	 *            时间格式.
	 * @return json格式的字符串.
	 */
	public static String toJson(List<?> beans, String[] properties,
			String dateFormat) {
		int page = 1, total = 0;
		if (null != beans) {
			total = beans.size();
		}
		return toJson(beans, properties, page, total, dateFormat);
	}

	/**
	 * 把列表信息转化成json格式.
	 * 
	 * @param beans
	 *            要输出到前台的列表信息.
	 * @param properties
	 *            前台需要展现的JavaBean属性.
	 * @param page
	 *            TinyGrid当前显示的页码数.
	 * @param total
	 *            查询出来的总记录数.
	 * @return json格式的字符串.
	 */
	public static String toJson(List<?> beans, String[] properties, int page,
			int total) {
		return toJson(beans, properties, page, total, null);
	}

	/**
	 * 把列表信息转化成json格式.
	 * 
	 * @param beans
	 *            要输出到前台的列表信息.
	 * @param properties
	 *            前台需要展现的JavaBean属性.
	 * @param page
	 *            TinyGrid当前显示的页码数.
	 * @param total
	 *            查询出来的总记录数.
	 * @param dateFormat
	 *            时间格式.
	 * @return json格式的字符串.
	 */
	public static String toJson(List<?> beans, String[] properties, int page,
			int total, String dateFormat) {
		if (CollectionUtils.isEmpty(beans) || ArrayUtils.isEmpty(properties)) {
			return generateJsonSkeleton(page, total, new StringBuffer());
		}
		String dateFormatOverride = StringUtils.defaultString(dateFormat, DEFAULT_DATE_FORMAT);
		StringBuffer cells = new StringBuffer();
		for (int i = 0, size = beans.size(); i < size; i++) {
			Object bean = beans.get(i);
			String cell = generateCellFormat(bean, properties, dateFormatOverride);
			if (i != 0) {
				cells.append(",");
			}
			cells.append(cell);
		}
		return generateJsonSkeleton(page, total, cells);
	}

	private static String generateCellFormat(Object bean, String[] properties, String dateFormat) {
		StringBuffer cell = new StringBuffer();
		cell.append("{");
		for (int i = 0, len = properties.length; i < len; i++) {
			String property = properties[i];
			
			Object propertyValue = null;
			try {
				propertyValue = PropertyUtils.getProperty(bean, property);
			} catch (Exception e) {
				propertyValue = "";
				LOG.info("提取属性:[" + property + "]失败" , e);
			}
			
			String cellValue = null;
			if (propertyValue == null) {
				cellValue = "";
			} else if (propertyValue instanceof Date) {
				SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
						dateFormat);
				cellValue = simpleDateFormat.format(propertyValue);
			} else {
				cellValue = propertyValue.toString();
			}
			if (i != 0) {
				cell.append(",");
			}
			cell.append("\"").append(property).append("\":\"").append(escapeCellValue(cellValue)).append("\"");
		}
		cell.append("}");
		return cell.toString();
	}

	private static String escapeCellValue(String cellValue) {
		return StringUtils.isBlank(cellValue) ? "" : cellValue.replaceAll("\"", "\\\\\"");
	}

	private static String generateJsonSkeleton(int page, int total,
			StringBuffer cells) {
		StringBuffer json = new StringBuffer();
		json.append("{\"page\":").append(page).append(",\"total\":").append(total);
		json.append(",\"rows\":[").append(cells).append("]");
		json.append("}");
		return json.toString();
	}
}
